package com.droidblackbox.record;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnKeyListener;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.telephony.SmsManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AlphaAnimation;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.droidblackbox.R;
import com.droidblackbox.info.BlackBox;
import com.droidblackbox.manager.C2DMManager;
import com.droidblackbox.manager.DisplayManager;
import com.droidblackbox.manager.FileManager;
import com.droidblackbox.manager.MapManager;
import com.droidblackbox.manager.MemoryManager;
import com.droidblackbox.manager.NotiManager;
import com.droidblackbox.manager.SystemManager;
import com.droidblackbox.manager.WASManager;
import com.droidblackbox.preference.PreferManager;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;

public class RecordView extends MapActivity implements SurfaceHolder.Callback,
		Handler.Callback, OnClickListener, OnSeekBarChangeListener {

	// Handler Message
	private static final int START_RECORDING = 0x548564;
	private static final int STOP_RECORDING = 0x58632;
	private static final int EXIT_RECORD = 0x5812632;
	private static final int START_BACK_THREAD = 0x7412;
	private static final int INIT_MEDIA_RECORDER = 0x9658;
	private static final int UPDATE_LOCATION = 0x8523;
	private static final int UPDATE_SPEED = 0x3214;
	private static final int ON_NOTIFICATION = 0x6587;

	private static final int SHOW_PLAY_IMAGE_VIEW = 0x5555;
	private static final int HIDE_PLAY_IMAGE_VIEW = 0x55;
	private static final int SHOW_STOP_IMAGE_VIEW = 0x55555;
	private static final int HIDE_STOP_IMAGE_VIEW = 0x555;

	// Thread Sleep
	private static final int BACK_THREAD_SLEEP = 0;

	private static final int RECORDING_NOTIFICATION_ID;

	static {
		RECORDING_NOTIFICATION_ID = 6587412;
	}

	public static SurfaceView surfaceView = null;
	public static SurfaceHolder surfaceHolder = null;
	public static Camera camera = null;
	public static MediaRecorder mediaRecorder = null;
	private boolean isRecording = false;

	private TextView locationTextView = null;
	private TextView speedTextView = null;
	private TextView locationHideTextView = null;
	private TextView speedHideTextView = null;

	private SeekBar brightnessSeekBar = null;

	private FrameLayout mapFrameLayout = null;
	private FrameLayout hideLayout = null;

	private ImageView playImageView = null;
	private ImageView stopImageView = null;
	private ImageView accidentImageView = null;

	private Button showRecordButton = null;
	private Button modeRecordButton = null;

	private int orientation = Configuration.ORIENTATION_PORTRAIT;
	private int showListIndex = -1;

	private Handler handler = null;
	private BackThread backThread = null;

	private boolean isInitialization = true;
	private boolean isShowDialog = true;
	private boolean isShake = false;
	private FiveMintueThread fiveMintueCountDown = null;

	private AlphaAnimation fade_in;
	private AlphaAnimation fade_out;

	// Record Timer
	private CountDownTimer timer;

	// File
	private String recordName = null;
	private File recordFolder = null;
	private File recordFile = null;
	private File blackboxFolder = null;
	private File blackboxFile = null;
	private List<Object> blackboxList = null;

	// Speed
	private double latitude;
	private double longitude;
	private double time;
	private double prelatitude;
	private double prelongitude;
	private double preTime;
	private double deltaTime;
	private float[] distance;
	private int speedInt;
	private double speedDouble;

	// MapView
	private boolean isLocationService = true;
	private LocationService locationService = null;
	private boolean isLoop = true;
	private boolean isSpeed = true;
	private boolean isAddress = true;

	// Sensor
	private enum Orientation {
		North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest
	};

	private String strOrientation = "";
	private SensorManager sensorManager = null;
	private Sensor sensorAcc = null;
	private Sensor sensorMag = null;
	private SensorAccelerometerListener accelerometerListener = null;
	private SensorMagneticFieldListener magneticFieldListener = null;

	private static final int DIALOG_PROGRESS = 1;
	private static final int MAX_PROGRESS = 0x200;
	private ProgressDialog progressDialog = null;

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		new AddAsyncTask().execute();

	}

	class AddAsyncTask extends AsyncTask<Void, Integer, Void> {

		@Override
		protected void onPreExecute() {
			showDialog(DIALOG_PROGRESS);

			progressDialog.setProgress(0);

			setContentView(R.layout.surfaceview);
			addContentView(R.layout.record_view);
			addContentView(R.layout.record_view_hide);

			init();
			setApplication();
			super.onPreExecute();
		}

		@Override
		protected Void doInBackground(Void... unused) {
			Resources r = Resources.getSystem();
			Configuration config = r.getConfiguration();
			orientation = config.orientation;
			handler.sendEmptyMessage(START_BACK_THREAD);
			int i = 0;
			while (isInitialization) {
				publishProgress(i++);
				SystemClock.sleep(10);

			}
			publishProgress(MAX_PROGRESS);
			return (null);
		}

		@Override
		protected void onProgressUpdate(Integer... progress) {
			progressDialog.setProgress(progress[0]);
		}

		@Override
		protected void onPostExecute(Void unused) {
			dismissDialog(DIALOG_PROGRESS);
			progressDialog.dismiss();

			handler.sendEmptyMessage(SHOW_PLAY_IMAGE_VIEW);
		}

		protected void onCancelled() {
			super.onCancelled();
		}
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);

		orientation = newConfig.orientation;

		setMapLayoutParams();

	}

	@Override
	public Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_PROGRESS:

			progressDialog = new ProgressDialog(RecordView.this);
			progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			progressDialog.setTitle("DrodiBlackBox");
			progressDialog.setMessage("Loading..... Please wait..");
			progressDialog.setCancelable(false);
			progressDialog.setMax(MAX_PROGRESS); // Max값 100
			return progressDialog;

		}
		return null;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (event.getAction() == KeyEvent.ACTION_DOWN
				&& keyCode == KeyEvent.KEYCODE_BACK) {
			if (hideLayout.isShown()) {
				hideLayoutClick();
				return true;
			}

			if (isRecording == true) {
				if (hideLayout.isShown()) {
					hideLayoutClick();
				} else {
					handler.sendEmptyMessage(SHOW_STOP_IMAGE_VIEW);
				}
			} else {
				if (playImageView.isShown()) {
					recordViewStop();
				} else {
					handler.sendEmptyMessage(SHOW_PLAY_IMAGE_VIEW);
				}

			}
		}
		return true;
	}

	private void addContentView(int layout) {
		LayoutInflater layoutInflater = LayoutInflater.from(this);
		View view = layoutInflater.inflate(layout, null);
		LayoutParams layoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT);
		addContentView(view, layoutParams);
	}

	private void init() {
		try {
			initApp();
			initSurface();
			initSensor();
			initCompoment();
			initMap();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void initApp() throws Exception {
		backThread = new BackThread();
		backThread.setName("BackThread");
		backThread.setDaemon(true);

		handler = new Handler(this);
		blackboxList = new ArrayList<Object>();

	}

	private void initSurface() throws Exception {
		surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
		surfaceHolder = surfaceView.getHolder();
		surfaceHolder.addCallback(this);
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	private void initCompoment() throws Exception {
		try {
			locationTextView = (TextView) findViewById(R.id.locationTextView);
			speedTextView = (TextView) findViewById(R.id.speedTextView);

			locationHideTextView = (TextView) findViewById(R.id.locationHideTextView);
			speedHideTextView = (TextView) findViewById(R.id.speedHideTextView);

			mapFrameLayout = (FrameLayout) findViewById(R.id.mapFrameLayout);
			hideLayout = (FrameLayout) findViewById(R.id.hideLayout);

			modeRecordButton = (Button) findViewById(R.id.modeRecordButton);
			showRecordButton = (Button) findViewById(R.id.showRecordButton);

			modeRecordButton.setOnClickListener(this);
			showRecordButton.setOnClickListener(this);

			playImageView = (ImageView) findViewById(R.id.recordPlayImageView);
			stopImageView = (ImageView) findViewById(R.id.recordStopImageView);
			accidentImageView = (ImageView) findViewById(R.id.accidentImageView);

			accidentImageView.setOnClickListener(this);
			playImageView.setOnClickListener(this);
			stopImageView.setOnClickListener(this);

			fade_in = new AlphaAnimation(0.0F, 1.0F);
			fade_in.setDuration(1000);

			fade_out = new AlphaAnimation(1.0F, 0.0F);
			fade_out.setDuration(1000);

			handler.sendEmptyMessage(HIDE_PLAY_IMAGE_VIEW);
			handler.sendEmptyMessage(HIDE_STOP_IMAGE_VIEW);

			brightnessSeekBar = (SeekBar) findViewById(R.id.setBrightnessSeekBar);
			brightnessSeekBar.setOnSeekBarChangeListener(this);
			brightnessSeekBar.setMax(15);
			brightnessSeekBar.setProgress(3);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void initSensor() throws Exception {
		sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

		sensorAcc = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		sensorMag = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

		accelerometerListener = new SensorAccelerometerListener();
		magneticFieldListener = new SensorMagneticFieldListener();

		sensorManager.registerListener(accelerometerListener, sensorAcc,
				SensorManager.SENSOR_DELAY_GAME);
		sensorManager.registerListener(magneticFieldListener, sensorAcc,
				SensorManager.SENSOR_DELAY_GAME);
		sensorManager.registerListener(magneticFieldListener, sensorMag,
				SensorManager.SENSOR_DELAY_GAME);
	}

	private void initMap() throws Exception {
		isLocationService = Boolean.parseBoolean(PreferManager
				.get(PreferManager.KEY_BOOLEAN_LOCATION_Service));
		locationService = new LocationService(
				(MapView) findViewById(R.id.mapView), isLocationService);

		if (isLocationService == true) {
			isLoop = true;
			MapManager.setInstance(this).onLocation();
		} else {
			isLoop = false;
			mapFrameLayout.setVisibility(View.INVISIBLE);
			mapFrameLayout.setVisibility(View.GONE);
			mapFrameLayout = null;
		}
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		try {

			int rotation = getWindowManager().getDefaultDisplay().getRotation();
			int degrees = 0;
			switch (rotation) {
			case Surface.ROTATION_0:
				degrees = 0;
				break;
			case Surface.ROTATION_90:
				degrees = 90;
				break;
			case Surface.ROTATION_180:
				degrees = 180;
				break;
			case Surface.ROTATION_270:
				degrees = 270;
				break;
			}

			int result = (90 - degrees + 360) % 360;
			camera.stopPreview();
			camera.setDisplayOrientation(result);
			camera.setParameters(camera.getParameters());
			camera.setPreviewDisplay(holder);
			camera.startPreview();
		} catch (Exception e) {
			stopCamera();
		}

		// 0 1280 720
		// 1 960 544
		// 2 800 480
		// 3 640 480
		// 4 480 320
	}

	public void surfaceCreated(SurfaceHolder holder) {
		surfaceHolder = holder;
		setApplication();
		setCameraPreview(holder, orientation);
		isInitialization = false;

		Toast.makeText(this, orientation + "On surface Created", 1000000)
				.show();
	}

	private void setCameraPreview(SurfaceHolder holder, int orientation) {
		try {
			int rotation = getWindowManager().getDefaultDisplay().getRotation();
			int degrees = 0;
			switch (rotation) {
			case Surface.ROTATION_0:
				degrees = 0;
				break;
			case Surface.ROTATION_90:
				degrees = 90;
				break;
			case Surface.ROTATION_180:
				degrees = 180;
				break;
			case Surface.ROTATION_270:
				degrees = 270;
				break;
			}

			int result = (90 - degrees + 360) % 360;

			camera = Camera.open();
			camera.setDisplayOrientation(result);
			camera.setParameters(camera.getParameters());
			camera.setPreviewDisplay(holder);
		} catch (Exception e) {
			stopCamera();
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
	}

	private void stopCamera() {
		try {
			if (camera != null) {
				camera.stopPreview();
				camera.release();
				camera = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void setApplication() {
		setCompoment();

		SystemManager.getInstance().onPowerMode(this);
		SystemManager.getInstance().onTelephony(this);
	}

	private void recordViewStop() {
		stopMediaRecorder();
		finish();

	}

	private void setCompoment() {
		try {
			hideLayout.setVisibility(View.GONE);
			showRecordButton.setVisibility(View.GONE);

			locationHideTextView.setVisibility(View.INVISIBLE);
			speedHideTextView.setVisibility(View.INVISIBLE);
			locationHideTextView.setVisibility(View.GONE);
			speedHideTextView.setVisibility(View.GONE);

			speedTextView.setTextSize(getResources().getDimension(
					R.dimen.record_speed_text));
			locationTextView.setTextSize(getResources().getDimension(
					R.dimen.record_address_text));

			speedTextView.setTextColor(getResources().getColor(
					R.color.speed_text_color));
			locationTextView.setTextColor(getResources().getColor(
					R.color.address_text_color));

			setMapLayoutParams();
		} catch (NullPointerException e) {
			SystemManager.getInstance().showToast(RecordView.this,
					"Sdcard check");
		}
	}

	private void setMapLayoutParams() {

		final int fillParent = android.widget.FrameLayout.LayoutParams.FILL_PARENT;
		FrameLayout.LayoutParams params = null;

		int w = DisplayManager.getInstance().getWidthPixels();
		int h = DisplayManager.getInstance().getHeightPixels();
		int pixels = 0;

		if (w < h)
			pixels = h / 2;
		else
			pixels = w / 2;

		final int dp = DisplayManager.getInstance().getDPfromPixel(pixels);
		switch (orientation) {
		case Configuration.ORIENTATION_PORTRAIT:
			params = new FrameLayout.LayoutParams(fillParent, dp);
			break;
		case Configuration.ORIENTATION_LANDSCAPE:
			params = new FrameLayout.LayoutParams(dp, fillParent);
			break;
		}

		if (mapFrameLayout != null)
			mapFrameLayout.setLayoutParams(params);

	}

	private void initMediaRecorder() {
		try {
			stopCamera();

			camera = Camera.open();
			Camera.Parameters params = camera.getParameters();
			camera.setParameters(params);
			Camera.Parameters p = camera.getParameters();

			final List<Size> listSize = p.getSupportedPreviewSizes();
			Size mPreviewSize = listSize.get(1);
			p.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			p.setPreviewFormat(PixelFormat.YCbCr_420_SP);
			camera.setParameters(p);

			try {
				camera.setPreviewDisplay(surfaceHolder);
				camera.startPreview();
			} catch (IOException e) {
				e.printStackTrace();
			}

			camera.unlock();

			boolean isAudio = Boolean.parseBoolean(PreferManager
					.get(PreferManager.KEY_BOOLEAN_AUDIO));

			mediaRecorder = new MediaRecorder();
			mediaRecorder.setCamera(camera);

			if (isAudio)
				mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
			mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

			mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
			if (isAudio)
				mediaRecorder
						.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
			mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);

			mediaRecorder.setOutputFile(getSaveFileName());
			mediaRecorder.setVideoSize(mPreviewSize.width, mPreviewSize.height);
			mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());

			mediaRecorder.prepare();
			mediaRecorder.start();

			isRecording = true;

		} catch (Exception e) {
			e.printStackTrace();
			releaseMediaRecorder();
			return;
		}
	}

	private void startMediaRecorder() {

		int sequence = Integer.parseInt(PreferManager
				.get(PreferManager.KEY_INT_SEQUENCE));

		timer = new CountDownTimer(sequence, 500) {
			boolean recordStart = true;

			@Override
			public void onFinish() {
				if (recordStart) {
					handler.sendEmptyMessage(EXIT_RECORD);
					recordStart = false;
				}
			}

			@Override
			public void onTick(long millisUntilFinished) {

			}
		};
		timer.start();

	}

	private void releaseMediaRecorder() {
		if (mediaRecorder == null)
			return;
		mediaRecorder.reset();
		mediaRecorder.release();
		mediaRecorder = null;

	}

	private void stopMediaRecorder() {
		try {

			isRecording = false;
			isLoop = false;

			NotiManager notiManager = new NotiManager(this);
			notiManager.cancel(RECORDING_NOTIFICATION_ID);

			SystemManager.getInstance().offPowerMode(this);
			SystemManager.getInstance().offTelephony(this);

			sensorManager.unregisterListener(accelerometerListener, sensorAcc);
			sensorManager.unregisterListener(magneticFieldListener, sensorAcc);
			sensorManager.unregisterListener(magneticFieldListener, sensorMag);

			locationService.disable();

			stopCamera();

			if (timer != null) {
				timer.cancel();
				timer = null;
			}

			SystemManager.getInstance().setScreenBrightness(this, -1.0f);

			writeLog(getNowTime(), "      Record Stopped !");

			if (mediaRecorder != null) {
				mediaRecorder.stop();
				mediaRecorder.release();
				onSaveEventFileWrite();

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void onSaveEventFileWrite() throws IOException {
		boolean isSave = Boolean.parseBoolean(PreferManager
				.get(PreferManager.KEY_BOOLEAN_SAVE));
		StringBuffer blackBoxName = new StringBuffer();
		StringBuffer recordName = new StringBuffer();

		final String header = getResources().getString(
				R.string.file_name_header);

		blackboxFolder = FileManager.getFile(FileManager.FOLDER_BLACK_BOX);
		if (isSave) {
			if (isShake) {
				recordName.append(header);
				recordName.append(this.recordName);
				recordName.append(FileManager.MEDIA_EXTENSION);

				blackBoxName.append(header);
				blackBoxName.append(this.recordName);
				blackBoxName.append(FileManager.DATA_EXTENSION);

			} else {
				recordName.append(this.recordName);
				recordName.append(FileManager.MEDIA_EXTENSION);

				blackBoxName.append(this.recordName);
				blackBoxName.append(FileManager.DATA_EXTENSION);
			}

			FileManager.renameTo(recordFile,
					new File(recordFolder, recordName.toString()));

			blackboxFile = new File(blackboxFolder, blackBoxName.toString());

			File temp2 = File.createTempFile(FileManager.TEMP,
					FileManager.DATA_EXTENSION, blackboxFolder);

			FileManager.renameTo(temp2, blackboxFile);

			temp2.deleteOnExit();

			FileManager.writeListObject(blackboxFile, blackboxList);

			onConnFileUpload();

		} else {
			if (isShake) {
				recordName.append(header);
				recordName.append(this.recordName);
				recordName.append(FileManager.MEDIA_EXTENSION);

				blackBoxName.append(header);
				blackBoxName.append(this.recordName);
				blackBoxName.append(FileManager.DATA_EXTENSION);

				FileManager.renameTo(recordFile, new File(recordFolder,
						recordName.toString()));

				blackboxFile = new File(blackboxFolder, blackBoxName.toString());

				File temp2 = File.createTempFile(FileManager.TEMP,
						FileManager.DATA_EXTENSION, blackboxFolder);

				FileManager.renameTo(temp2, blackboxFile);

				temp2.deleteOnExit();

				FileManager.writeListObject(blackboxFile, blackboxList);

				onConnFileUpload();

			} else {
				recordFile.delete();
			}
		}

		onConnFileUpload();

	}

	ProgressBar progressBar;

	private void onConnFileUpload() {
		try {

			if (recordFile != null) {
				FileInputStream fis = new FileInputStream(recordFile);
				WASManager.conn(fis, recordFile.getName());
			}

			if (blackboxFile != null) {
				FileInputStream fis = new FileInputStream(blackboxFile);
				WASManager.conn(fis, blackboxFile.getName());
			}
		} catch (Exception e) {
		}

	}

	private StringBuffer getNowTime() {
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH) + 1;
		int day = calendar.get(Calendar.DAY_OF_MONTH);

		int hour = calendar.get(Calendar.HOUR_OF_DAY);
		int minute = calendar.get(Calendar.MINUTE);
		int second = calendar.get(Calendar.SECOND);

		StringBuffer sb = new StringBuffer();

		sb.append(year).append(".");
		sb.append(month).append(".");
		sb.append(day).append("_");
		sb.append(hour).append(".");
		sb.append(minute).append(".");
		sb.append(second);

		return sb;
	}

	private String getSaveFileName() throws Exception {
		writeLog(getNowTime(), "      Record Started!");
		return createFiles(getNowTime());
	}

	private String createFiles(StringBuffer sb) throws IOException {
		recordName = sb.toString();

		recordFolder = FileManager.getFile(FileManager.FOLDER_RECORD);
		recordFile = new File(recordFolder, recordName
				+ FileManager.MEDIA_EXTENSION);

		File temp1 = File.createTempFile(FileManager.TEMP,
				FileManager.MEDIA_EXTENSION, recordFolder);

		FileManager.renameTo(temp1, recordFile);

		temp1.deleteOnExit();

		return recordFile.getAbsolutePath();
	}

	private void writeLog(StringBuffer sb, String msg) {
		FileManager.writeLog(sb.append(msg).append("\r\n"));
	}

	private void onNotification() {
		Intent intent = new Intent(this, RecordView.class);
		String ticker = "Start Recording...";
		String text = "DroidBlackBox Recording";
		int flags = Notification.FLAG_ONGOING_EVENT;

		NotiManager noti = new NotiManager(this);

		noti.setId(RECORDING_NOTIFICATION_ID);
		noti.setTicker(ticker);
		noti.setText(text);
		noti.setIntent(intent);
		noti.setFlags(flags);
		noti.onNotification();

	}

	public boolean handleMessage(Message msg) {

		switch (msg.what) {
		case START_RECORDING:
			startMediaRecorder();
			break;
		case STOP_RECORDING:
			stopMediaRecorder();
			break;
		case EXIT_RECORD:
			recordViewStop();
			break;
		case INIT_MEDIA_RECORDER:
			initMediaRecorder();
			break;
		case UPDATE_LOCATION:
			setLocation();
			break;
		case UPDATE_SPEED:
			setSpeed();
			break;
		case ON_NOTIFICATION:
			onNotification();
			break;
		case START_BACK_THREAD:
			backThread.start();
			break;
		case SHOW_PLAY_IMAGE_VIEW:
			playImageView.setFocusable(true);
			playImageView.setClickable(true);
			playImageView.setVisibility(View.VISIBLE);
			playImageView.startAnimation(fade_in);
			break;
		case HIDE_PLAY_IMAGE_VIEW:
			playImageView.setFocusable(false);
			playImageView.setClickable(false);
			playImageView.setVisibility(View.GONE);
			playImageView.startAnimation(fade_out);
			break;
		case SHOW_STOP_IMAGE_VIEW:
			stopImageView.setFocusable(true);
			stopImageView.setClickable(true);
			stopImageView.setVisibility(View.VISIBLE);
			stopImageView.startAnimation(fade_in);
			break;
		case HIDE_STOP_IMAGE_VIEW:
			stopImageView.setFocusable(false);
			stopImageView.setClickable(false);
			stopImageView.setVisibility(View.GONE);
			stopImageView.startAnimation(fade_out);
			break;
		}

		return true;
	}

	private void setSpeed() {
		try {
			latitude = MapManager.getInstance().getLatitudeDouble();
			longitude = MapManager.getInstance().getLongitudeDouble();
			time = MapManager.getInstance().getTimeDouble();
			if (isSpeed) {
				isSpeed = false;
			} else {
				deltaTime = (time - preTime);
				distance = new float[3];
				MapManager.getInstance().getDistanceBetween(prelatitude,
						prelongitude, latitude, longitude, distance);
				speedDouble = distance[0] / deltaTime * 3600;
				speedInt = (int) speedDouble;

				speedTextView.setText(Integer.toString(speedInt) + " Km/h");
				speedHideTextView.setText(Integer.toString(speedInt) + " Km/h");
			}

			int index = 0;
			if (blackboxList.size() - 1 < 0)
				index = 0;
			else
				index = blackboxList.size();

			BlackBox blackBox = new BlackBox();
			blackBox.setIndex(index);
			blackBox.setTime(getNowTime().toString());
			blackBox.setLatitude(MapManager.getInstance().getLatitudeInt());
			blackBox.setLongitude(MapManager.getInstance().getLongitudeInt());
			blackBox.setOrientation(strOrientation);
			blackBox.setSpeed(speedInt);
			blackBox.setAddress(MapManager.getInstance().getAddress());
			blackBox.setAccident(isShake);

			blackboxList.add(blackBox);

			prelatitude = latitude;
			prelongitude = longitude;
			preTime = time;
			speedInt = 0;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void setLocation() {
		final String address = MapManager.getInstance().getAddress();
		if (address == null || address.equals("")
				|| address.equals(MapManager.ERROR)) {

			StringBuffer buffer = new StringBuffer();
			buffer.append(MapManager.getInstance().getLatitudeInt());
			buffer.append(" , ");
			buffer.append(MapManager.getInstance().getLongitudeInt());

			if (locationTextView.isShown())
				locationTextView.setText(buffer.toString());

			if (locationHideTextView.isShown())
				locationHideTextView.setText(buffer.toString());
			isAddress = true;
		} else {
			if (isAddress == true) {
				Toast.makeText(RecordView.this,
						getResources().getString(R.string.record_location),
						Toast.LENGTH_SHORT).show();
				isAddress = false;
			}

			if (locationTextView.isShown())
				locationTextView.setText(address);

			if (locationHideTextView.isShown())
				locationHideTextView.setText(address);
		}
	}

	public void setExit() {
		isLoop = false;
	}

	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		float f = 1.0F;
		switch (progress) {
		case 0:
			f = 0.1F;
			break;
		case 1:
		case 2:
			f = 0.2F;
			break;
		case 3:
		case 4:
			f = 0.3F;
			break;
		case 5:
		case 6:
			f = 0.4F;
			break;
		case 7:
		case 8:
			f = 0.5F;
			break;
		case 9:
		case 10:
			f = 0.6F;
			break;
		case 11:
		case 12:
			f = 0.7F;
			break;
		case 13:
		case 14:
			f = 0.8F;
			break;
		case 15:
			f = 0.9F;
			break;
		}
		SystemManager.getInstance().setScreenBrightness(this, f);

	}

	public void onStartTrackingTouch(SeekBar seekBar) {
		seekBar.setProgress(brightnessSeekBar.getProgress());

	}

	public void onStopTrackingTouch(SeekBar seekBar) {
		brightnessSeekBar.setProgress(seekBar.getProgress());

	}

	public void onClick(View v) {
		String s = null;

		if (v == playImageView) {
			handler.sendEmptyMessage(INIT_MEDIA_RECORDER);
			handler.sendEmptyMessage(START_RECORDING);
			handler.sendEmptyMessage(ON_NOTIFICATION);

			playImageView.setFocusable(false);
			playImageView.setClickable(false);
			playImageView.setVisibility(View.GONE);

			return;

		}

		if (v == stopImageView) {
			showDialog(DIALOG_PROGRESS);
			handler.sendEmptyMessage(EXIT_RECORD);

			Intent intent = getIntent();
			setResult(RESULT_OK, intent);
			finish();
			dismissDialog(DIALOG_PROGRESS);
			return;
		}

		if (v == accidentImageView) {
			onPopupDialog(true);
			return;
		}

		if (v == showRecordButton) {
			hideLayoutClick();
			return;
		}

		if (v == modeRecordButton) {
			showListIndex++;
			switch (showListIndex) {
			case 0:

				if (mapFrameLayout == null) {
					s = getResources().getString(R.string.record_mode_change_1);
					showListIndex++;
					break;
				}

				s = getResources().getString(R.string.record_mode_change_2);
				final int fillParent = android.widget.FrameLayout.LayoutParams.FILL_PARENT;
				FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
						fillParent, fillParent);

				mapFrameLayout.setLayoutParams(params);
				break;
			case 1:
				if (mapFrameLayout == null) {
					showListIndex++;
					break;
				}

				s = getResources().getString(R.string.record_mode_change_3);
				setMapLayoutParams();
				mapFrameLayout.setVisibility(View.INVISIBLE);
				break;
			case 2:
				s = getResources().getString(R.string.record_mode_change_4);

				hideLayout.setVisibility(View.VISIBLE);
				showRecordButton.setVisibility(View.VISIBLE);

				locationHideTextView.setVisibility(View.VISIBLE);
				speedHideTextView.setVisibility(View.VISIBLE);

				showListIndex = -1;
				break;
			}
		}

		SystemManager.getInstance().showToast(RecordView.this, s);
	}

	private void hideLayoutClick() {
		if (mapFrameLayout != null)
			mapFrameLayout.setVisibility(View.VISIBLE);

		hideLayout.setVisibility(View.INVISIBLE);

		String s = getResources().getString(R.string.record_mode_change_1);
		SystemManager.getInstance().showToast(RecordView.this, s);
	}

	private void onPopupDialog(boolean popup) {
		if (popup)
			showPopupDialog();
	}

	private void showPopupDialog() {

		handler.sendEmptyMessage(STOP_RECORDING);

		final String title = getResources()
				.getString(R.string.popup_call_title);

		final String phone1 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE1);
		final String phone2 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE2);
		final String phone3 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE3);

		final int phoneNumberLength = 8;

		final Dialog dialog = new Dialog(RecordView.this);
		dialog.setContentView(R.layout.record_popup_call);
		dialog.setTitle(title);
		dialog.setOnKeyListener(new OnKeyListener() {

			public boolean onKey(DialogInterface dialog, int keyCode,
					KeyEvent event) {

				if (event.getAction() == KeyEvent.ACTION_DOWN
						&& keyCode == KeyEvent.KEYCODE_BACK) {

					fiveMintueCountDown.isCount = false;
					dialog.cancel();
					dialog.dismiss();
					finish();
				}
				return true;
			}
		});

		Button button1 = (Button) dialog.findViewById(R.id.phone1);

		if (phone1.equals("") || phone1.length() < phoneNumberLength) {
			button1.setVisibility(View.GONE);
		} else {
			button1.setText(phone1);
			button1.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					startActivity(new Intent(Intent.ACTION_CALL, Uri
							.parse("tel:" + phone1)));

				}
			});
		}

		Button button2 = (Button) dialog.findViewById(R.id.phone2);

		if (phone2.equals("") || phone2.length() < phoneNumberLength) {
			button2.setVisibility(View.INVISIBLE);
		} else {
			button2.setText(phone2);
			button2.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					startActivity(new Intent(Intent.ACTION_CALL, Uri
							.parse("tel:" + phone2)));

				}
			});
		}

		Button button3 = (Button) dialog.findViewById(R.id.phone3);
		if (phone3.equals("") || phone3.length() < phoneNumberLength) {
			button3.setVisibility(View.INVISIBLE);
		} else {
			button3.setText(phone3);
			button3.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					startActivity(new Intent(Intent.ACTION_CALL, Uri
							.parse("tel:" + phone3)));

				}
			});
		}

		Button button4 = (Button) dialog.findViewById(R.id.callcancel);
		button4.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				dialog.cancel();
				fiveMintueCountDown.stop();
				recordViewStop();

			}
		});

		// if (isRecording)
		dialog.show();

		TextView timeTextView = (TextView) dialog
				.findViewById(R.id.timeTextView);

		ProgressBar bar = (ProgressBar) dialog
				.findViewById(R.id.timeProgressBar);

		fiveMintueCountDown = new FiveMintueThread(timeTextView, bar);
		fiveMintueCountDown.start();

		// onPushSend(true, phone1);
		// onPushSend(true, phone2);
		// onPushSend(true, phone3);

	}

	private void onPushSend(boolean push, String number) {
		if (push)
			sendMessage(number);
	}

	private void sendMessage(String number) {
		Map<String, String> message = new HashMap<String, String>();
		String myNumber = C2DMManager.getInstance().getNumber();
		message.put(C2DMManager.KEY_PUSH_NUMBER, myNumber);
		message.put(C2DMManager.KEY_PUSH_SUBMESSAGE,
				getResources().getString(R.string.receive_message));
		message.put(C2DMManager.KEY_PUSH_1, "msg1");
		message.put(C2DMManager.KEY_PUSH_2, "msg2");
		message.put(C2DMManager.KEY_PUSH_3, "msg3");
		message.put(C2DMManager.KEY_PUSH_4, "msg4");
		message.put(C2DMManager.KEY_PUSH_5, "msg5");

		C2DMManager.push(number, message);

		SystemManager.getInstance()
				.showToast(RecordView.this, "메시지를 전송 하였습니다.");
	}

	/**
	 * Sms Send
	 * 
	 * @param sms
	 */
	private void onSendSms(boolean sms) {
		if (sms == false)
			return;

		if (sms == true)
			return;
		final String phone1 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE1);
		final String phone2 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE2);
		final String phone3 = PreferManager
				.get(PreferManager.KEY_STRING_PHONE3);

		List<String> phoneList = new ArrayList<String>();

		phoneList.add(phone1);
		phoneList.add(phone2);
		phoneList.add(phone3);

		String phoneMessage = PreferManager
				.get(PreferManager.KEY_STRING_PHONE_MESSAGE);
		boolean isLocationSms = Boolean.parseBoolean(PreferManager
				.get(PreferManager.KEY_BOOLEAN_LOCATION_SMS));

		StringBuffer sb = new StringBuffer();

		sb.append(phoneMessage);

		if (isLocationService == true && isLocationSms == true) {
			sb.append(", ");
			sb.append(MapManager.getInstance().getAddress());
		}

		SmsManager smsManager = SmsManager.getDefault();

		for (String string : phoneList) {
			if (string != null && string.length() > 8) {
				smsManager.sendTextMessage(string, null, sb.toString(), null,
						null);
			}
		}
		SystemManager.getInstance().showToast(RecordView.this,
				"문자 메시지를 전송 하였습니다.");
	}

	private void writeLog() {
		int collisionHour, collisionMinute, collisionSecond;

		Calendar calendar = Calendar.getInstance();
		collisionHour = calendar.get(Calendar.HOUR_OF_DAY);
		collisionMinute = calendar.get(Calendar.MINUTE);
		collisionSecond = calendar.get(Calendar.SECOND);

		StringBuffer sb = new StringBuffer();
		sb.append(recordName);
		sb.append("->");
		sb.append(collisionHour);
		sb.append(".");
		sb.append(collisionMinute);
		sb.append(".");
		sb.append(collisionSecond);
		sb.append("  ");
		sb.append("Accident !!!");
		sb.append("\r\n");

		FileManager.writeLog(sb);
	}

	class MemoryStateThread extends Thread {
		@Override
		public void run() {
			final long totalSize = Long.parseLong(PreferManager
					.get(PreferManager.KEY_LONG_MEMORY_SIZE));
			if (isRecording == true) {
				final long app = MemoryManager.getInstance()
						.getUsingAppMemorySize();

				if (totalSize < app) {

					try {
						File f = FileManager.getLastModifiedFile();
						f.delete();
					} catch (NullPointerException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

			}
		}
	}

	class FiveMintueThread extends Thread {
		private int minute;
		private int minuteCount = 0;
		private int second = 10;
		private int oneSecond = 1000;
		private int progress;
		private TextView textView = null;
		private ProgressBar bar = null;

		public boolean isCount = true;

		public FiveMintueThread(TextView textView, ProgressBar bar) {
			this.textView = textView;
			this.bar = bar;

			if (minuteCount == 0) {
				minuteCount = 1;
				minute = 0;
			} else {
				minute = minuteCount;
			}

			progress = (second * minuteCount);
		}

		public void run() {
			bar.setMax(progress);
			bar.setBackgroundColor(Color.WHITE);
			textView.setTextColor(Color.RED);

			while (isCount) {
				onTick();
				System.out.println(isCount);
			}
		}

		private void onTick() {
			second--;
			if (second == 0) {
				second = 60;
				minute--;
				if (minute <= 0) {
					second = 0;
					minute = 0;

					isCount = false;
					showAlertDialog();
				}
			}

			runOnUiThread(new Runnable() {

				public void run() {
					StringBuffer buffer = new StringBuffer();
					buffer.append(minute);
					buffer.append(" : ");
					buffer.append(second);

					bar.incrementProgressBy(1);
					textView.setText(buffer);
				}
			});

			try {
				Thread.sleep(oneSecond);
			} catch (InterruptedException e) {
				// TODO: handle exception
			}

		}

		private void showAlertDialog() {
			final String alertTitle = "Title";
			final String buttonMessage = "Message";
			final String buttonYes = "Y";
			final String buttonNo = "N";

			new AlertDialog.Builder(RecordView.this)
					.setTitle(alertTitle)
					.setMessage(buttonMessage)
					.setPositiveButton(buttonYes,
							new DialogInterface.OnClickListener() {

								public void onClick(DialogInterface dialog,
										int which) {
								}
							})
					.setNegativeButton(buttonNo,
							new DialogInterface.OnClickListener() {

								public void onClick(DialogInterface dialog,
										int which) {
								}
							}).show();

		}
	}

	class BackThread extends Thread {
		@Override
		public void run() {
			synchronized (this) {
				try {
					while (isLoop) {
						MapManager.getInstance().onLocation();
						Thread.sleep(BACK_THREAD_SLEEP);
						handler.sendEmptyMessage(UPDATE_LOCATION);
						handler.sendEmptyMessage(UPDATE_SPEED);
					}
				} catch (Exception e) {
					run();
				}
			}

		}
	}

	class LocationService {
		private MapController mapController = null;
		private LocationOverlay locationOverlay = null;

		public LocationService(MapView mapView, boolean isService) {
			if (isService == true)
				setMapView(mapView);
			else
				mapView.setVisibility(View.GONE);
		}

		private void setMapView(final MapView mapView) {
			mapController = mapView.getController();
			mapController.setZoom(18);
			// mapView.setBuiltInZoomControls(false);

			GeoPoint geoPoint = new GeoPoint(0, 0);
			mapController.setCenter(geoPoint);

			locationOverlay = new LocationOverlay(RecordView.this, mapView);
			List<Overlay> overlays = mapView.getOverlays();
			overlays.add(locationOverlay);

			locationOverlay.runOnFirstFix(new Runnable() {

				public void run() {
					try {
						mapView.getController().animateTo(
								locationOverlay.getMyLocation());
					} catch (Exception e) {
					}
				}
			});

			locationOverlay.enableCompass();
			locationOverlay.enableMyLocation();
		}

		public void disable() {
			if (locationOverlay == null)
				return;

			locationOverlay.disableCompass();
			locationOverlay.disableMyLocation();

			MapManager.getInstance().removeUpdate();

		}
	}

	class LocationOverlay extends MyLocationOverlay {

		public LocationOverlay(Context context, MapView mapView) {
			super(context, mapView);
		}

		@Override
		protected boolean dispatchTap() {
			String s = MapManager.getInstance().getAddress();
			SystemManager.getInstance().showToast(RecordView.this, s);
			return false;
		}
	}

	class SensorAccelerometerListener implements SensorEventListener {

		private long lastTime;
		private float speed;
		private float lastX;
		private float lastY;
		private float lastZ;

		private float x, y, z;
		private long collisionTime, lastCollisionTime;

		public SensorAccelerometerListener() {
			lastCollisionTime = System.currentTimeMillis();
		}

		public void onAccuracyChanged(Sensor sensor, int accuracy) {

		}

		public void onSensorChanged(SensorEvent event) {
			if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
				synchronized (event) {
					onChanged(event);

				}
			}
		}

		private void onChanged(SensorEvent event) {
			long currentTime = System.currentTimeMillis();
			long gebOfTime = currentTime - lastTime;

			if (gebOfTime > 100) {
				lastTime = currentTime;

				x = event.values[SensorManager.DATA_X];
				y = event.values[SensorManager.DATA_Y];
				z = event.values[SensorManager.DATA_Z];

				speed = Math.abs(x + y + z - lastX - lastY - lastZ) / gebOfTime
						* 10000;

				int shakeThreshold = Integer.parseInt(PreferManager
						.get(PreferManager.KEY_INT_SHAKE_THRESHOLD));
				if (speed > shakeThreshold) {

					isShake = true;

					collisionTime = lastTime;

					if (collisionTime - lastCollisionTime > 500 && isShowDialog) {

						final boolean isPopup = Boolean
								.parseBoolean(PreferManager
										.get(PreferManager.KEY_BOOLEAN_POPUP));

						final boolean isSms = Boolean
								.parseBoolean(PreferManager
										.get(PreferManager.KEY_BOOLEAN_SMS));

						onPopupDialog(isPopup);
						onSendSms(isSms);

						// Log file Save
						writeLog();

						isShowDialog = false;
					}

					lastCollisionTime = collisionTime;
				}

				lastX = event.values[SensorManager.DATA_X];
				lastY = event.values[SensorManager.DATA_Y];
				lastZ = event.values[SensorManager.DATA_Z];
			}

		}

	}

	class SensorMagneticFieldListener implements SensorEventListener {

		private float[] mR = new float[9];
		private float[] mI = new float[9];
		private float[] mV = new float[3];
		private float[] mGravity = null;
		private float[] mGeoMagnetic = null;
		private int mOrientCount;
		private final static int FREQ = 20;

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
		}

		public void onSensorChanged(SensorEvent event) {
			if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
				mGravity = event.values.clone();
			} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
				mGeoMagnetic = event.values.clone();
			}

			if (mOrientCount++ % FREQ != 0)
				return;

			if (mGravity != null && mGeoMagnetic != null) {
				SensorManager.getRotationMatrix(mR, mI, mGravity, mGeoMagnetic);
				SensorManager.getOrientation(mR, mV);

				mV[0] = (float) Math.toDegrees(mV[0]);

				if (mV[0] < 0)
					mV[0] += 360;

				parseOrintation(mV[0]);
			}
		}

		private void parseOrintation(float value) {
			if (0 <= value && value < 22.5) {
				strOrientation = Orientation.North.toString();
			} else if (22.5 <= value && value < 45) {
				strOrientation = Orientation.NorthEast.toString();
			} else if (45 <= value && value < 67.5) {
				strOrientation = Orientation.NorthEast.toString();
			} else if (67.5 <= value && value < 90) {
				strOrientation = Orientation.East.toString();
			} else if (90 <= value && value < 112.5) {
				strOrientation = Orientation.East.toString();
			} else if (112.5 <= value && value < 135) {
				strOrientation = Orientation.SouthEast.toString();
			} else if (135 <= value && value < 157.5) {
				strOrientation = Orientation.SouthEast.toString();
			} else if (157.5 <= value && value <= 180) {
				strOrientation = Orientation.South.toString();
			} else if (180 <= value && value < 202.5) {
				strOrientation = Orientation.South.toString();
			} else if (202.5 <= value && value < 225) {
				strOrientation = Orientation.SouthWest.toString();
			} else if (225 <= value && value < 247.5) {
				strOrientation = Orientation.SouthWest.toString();
			} else if (247.5 <= value && value < 270) {
				strOrientation = Orientation.West.toString();
			} else if (270 <= value && value < 292.5) {
				strOrientation = Orientation.West.toString();
			} else if (292.5 <= value && value < 315) {
				strOrientation = Orientation.NorthWest.toString();
			} else if (315 <= value && value <= 337.5) {
				strOrientation = Orientation.NorthWest.toString();
			} else if (337.5 <= value && value <= 360) {
				strOrientation = Orientation.North.toString();
			}

		}
	}
}
